package ru.cannabis;

import ru.cannabis.job.AbstractJob;
import org.apache.commons.lang.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;

public class PolicyServer extends AbstractJob
{
	private int port = 843;
	private List<Integer> protectPorts;
	private List<String> domains;
	private boolean running = false;

	private ServerSocket serverSocket;

	public PolicyServer(int port, List<String> domains, List<Integer> protectPorts)
    {
		this.port = port;
		this.domains = domains;
		this.protectPorts = protectPorts;
	}

	public void stop()
    {
		this.running = false;
	}

	@Override
	protected void execute()
    {
		try
        {
			serverSocket = new ServerSocket(this.port);
		}
        catch (IOException e)
        {
			log.error("Policy Server was not created. " + e.getMessage());
            System.out.println("Policy Server was not created. " + e.getMessage());
		}

		if (serverSocket == null) return;

		log.info(String.format("Policy Server started on port %d", port));
        System.out.println(String.format("Policy Server started on port %d", port));
		this.running = true;

		while (this.running)
        {

			Socket incoming;
			try
            {
				incoming = serverSocket.accept();

				BufferedReader readerIn = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
				PrintStream printOut = new PrintStream(incoming.getOutputStream());

				boolean isReadable = true;
				String request = "";
				while (isReadable)
                {
					if (request.compareTo("<policy-file-request/>\0") != 0)
                    {
						//Read character
						request += (char) readerIn.read();
						// If request start character doesn't meet our expectations then just return
						if (request == null || request.charAt(0) != '<')
                        {
							isReadable = false;
						}
					}
                    else
                    {
						InetAddress inetAddress = incoming.getInetAddress();
						log.info(String.format("%s [ %s ] Write: %s", inetAddress.getHostName(), inetAddress.getHostAddress(), request));
						String response = getPolicyResponse();
						printOut.print(response);
						log.info(String.format("%s [ %s ] Read: %s", inetAddress.getHostName(), inetAddress.getHostAddress(), response));
						isReadable = false;
					}
				}
				incoming.close();

			}
            catch (IOException e)
            {
				log.error("Policy Server was not created. " + e.getMessage());
				e.printStackTrace();
			}

		}

		log.info("Policy Server closed");
        System.out.println("Policy Server closed");
	}

	private String getPolicyResponse()
    {
		StringBuilder response = new StringBuilder();

		response.append("<?xml version=\"1.0\"?><cross-domain-policy>");
		for (String domain : domains)
        {
			response.append(String.format("<allow-access-from domain=\"%s\" secure=\"false\" to-ports=\"%s\"/>", domain, StringUtils.join(protectPorts, ",")));
		}
		response.append("</cross-domain-policy>\0");

		return response.toString();
	}

}
